using System;
using System.Collections.Generic;

namespace Atomic.Libraries
{
	public static class ZipExtensions
	{
		public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, IEnumerable<TThird> third, Func<TFirst, TSecond, TThird, TResult> resultSelector)
		{
			// http://stackoverflow.com/a/12641379
			using (IEnumerator<TFirst> iterator1 = first.GetEnumerator())
			{
				using (IEnumerator<TSecond> iterator2 = second.GetEnumerator())
				{
					using (IEnumerator<TThird> iterator3 = third.GetEnumerator())
					{
						while (iterator1.MoveNext() && iterator2.MoveNext() && iterator3.MoveNext())
						{
							yield return resultSelector(iterator1.Current, iterator2.Current, iterator3.Current);
						}
					}
				}
			}
		}

		public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TFourth, TFifth, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, IEnumerable<TThird> third, IEnumerable<TFourth> fourth, IEnumerable<TFifth> fifth, Func<TFirst, TSecond, TThird, TFourth, TFifth, TResult> resultSelector)
		{
			// http://stackoverflow.com/a/12641379
			using (IEnumerator<TFirst> iterator1 = first.GetEnumerator())
			{
				using (IEnumerator<TSecond> iterator2 = second.GetEnumerator())
				{
					using (IEnumerator<TThird> iterator3 = third.GetEnumerator())
					{
						using (IEnumerator<TFourth> iterator4 = fourth.GetEnumerator())
						{
							using (IEnumerator<TFifth> iterator5 = fifth.GetEnumerator())
							{
								while (iterator1.MoveNext() && iterator2.MoveNext() && iterator3.MoveNext() && iterator4.MoveNext() && iterator5.MoveNext())
								{
									yield return resultSelector(iterator1.Current, iterator2.Current, iterator3.Current, iterator4.Current, iterator5.Current);
								}
							}
						}
					}
				}
			}
		}
	}
}
